import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.bigmodel.contant.intelligentWorkOrder.Punctuation;
import com.bigmodel.contant.meeting.personNumSlot.PersonNumSlot;
import com.bigmodel.contant.meeting.roomSlot.RoomSlot;
import com.bigmodel.contant.meeting.topicWordSlot.TopicWordSlot;
import com.bigmodel.entity.QAEntity;
import com.bigmodel.entity.SoltEntity;
import com.bigmodel.entity.TimeEntity;
import com.bigmodel.util.ConferenceTimeUtils;
import com.bigmodel.util.ExcelUtil;
import com.bigmodel.util.FtlUtil;
import com.bigmodel.util.TimeUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;

public class IntelligentWorkOrder_V3 {

    private final static String OUT_PATH = "E:\\bld\\大模型\\语料\\长沙银行\\intelligentWorkOrder_v2\\";

    private final static String FREEMARKER_BASE_PATH = "sft/intelligentWorkOrder_v3/";

    /**
     * 标点符号
     */
    private static List<String> LIST_PUNCTUATION = null;
    /**
     * 会议室房号
     */
    private static List<String> LIST_ROOM_SLOT = null;

    /**
     * 会议室主题
     */
    private static List<String> LIST_TOPIC_WORD_SLOT_ONE = null;
    private static List<String> LIST_TOPIC_WORD_SLOT_TWO = null;
    private static List<String> LIST_TOPIC_WORD_SLOT_THREE = null;
    /**
     * 人数规模
     */
    private static List<String> LIST_PERSON_NUM_SLOT_ONE = null;




    static {
        LIST_PUNCTUATION = ListUtil.toList(Punctuation.LIST_PUNCTUATION);

        LIST_ROOM_SLOT = ListUtil.toList(RoomSlot.LIST_ROOM_SLOT);

        LIST_TOPIC_WORD_SLOT_ONE = ListUtil.toList(TopicWordSlot.LIST_TOPIC_WORD_SLOT_ONE);
        LIST_TOPIC_WORD_SLOT_TWO = ListUtil.toList(TopicWordSlot.LIST_TOPIC_WORD_SLOT_TWO);
        LIST_TOPIC_WORD_SLOT_THREE = ListUtil.toList(TopicWordSlot.LIST_TOPIC_WORD_SLOT_THREE);

        LIST_PERSON_NUM_SLOT_ONE = ListUtil.toList(PersonNumSlot.LIST_PERSON_NUM_SLOT_ONE);
    }


    public static void main(String[] args) {
        /**
         * 提取时间 今天15点、明天14点12，大后天9点
         * 早上1点，上午2点，下午3点，今天4点
         * 本周,下周
         * 几月几日,几月几号,几月几,几年几月几日,几点
         */
        T001();
    }

    private static void T001() {
        Map<String, TimeEntity> timeEntityMap = new HashMap<>();
        timeEntityMap.putAll(ConferenceTimeUtils.T001());
        timeEntityMap.putAll(ConferenceTimeUtils.T002());
        timeEntityMap.putAll(ConferenceTimeUtils.T003());
        timeEntityMap.putAll(ConferenceTimeUtils.T004());
        timeEntityMap.putAll(ConferenceTimeUtils.T005());
        timeEntityMap.putAll(ConferenceTimeUtils.T006());
        timeEntityMap.putAll(ConferenceTimeUtils.T007());
        timeEntityMap.putAll(ConferenceTimeUtils.T008());
        timeEntityMap.putAll(ConferenceTimeUtils.T009());
        creatExcel( timeEntityMap, "T001\\");
    }

    private static void creatExcel(Map<String, TimeEntity> timeEntityMap, String catalogue) {
        long startTime = System.currentTimeMillis();

        // Map<词槽名称，Map<词槽描述，词槽信息Entity>
        Map<String, Map<String, TimeEntity>> allSoltMap = new HashMap<>();
        // Map<词槽顺序（方便随机抽取），词槽信息Entity>
        Map<Integer, SoltEntity> soltEntityMap = new HashMap<>();


        Map<String, TimeEntity> topicWordMap = new HashMap<>();
        List<String> topicWordSlots = getTopicWordSlot(topicWordMap);
        soltEntityMap.put(0, SoltEntity.builder().solts(topicWordSlots).soltMap(topicWordMap).build());
        allSoltMap.put("topic", topicWordMap);


        Map<String, TimeEntity> personNumSlotMap = new HashMap<>();
        List<String> personNumSlots = getPersonNumSlot(personNumSlotMap);
        soltEntityMap.put(1, SoltEntity.builder().solts(personNumSlots).soltMap(personNumSlotMap).build());
        allSoltMap.put("personNum", personNumSlotMap);

        List<String>  times = random200List(new ArrayList<>(timeEntityMap.keySet()));
        soltEntityMap.put(2, SoltEntity.builder().solts(times).soltMap(timeEntityMap).build());
        allSoltMap.put("time", timeEntityMap);


        creatExcel(allSoltMap, soltEntityMap, catalogue);


        long endTime = System.currentTimeMillis();
        long executionTime = endTime - startTime;
        System.out.println("程序执行时间：" + executionTime + " 毫秒");

    }

    /**
     * 创建excel
     *
     * @param allSoltMap    Map<词槽名称，Map<词槽描述，词槽信息Entity>
     * @param soltEntityMap Map<词槽顺序（方便随机抽取），词槽信息Entity>
     * @param catalogue     目录
     */
    private static void creatExcel(Map<String, Map<String, TimeEntity>> allSoltMap, Map<Integer, SoltEntity> soltEntityMap, String catalogue) {
        List<QAEntity> allEntityList = new ArrayList<>();

        String code = "T00";
        // 一种
        List<List<Integer>> oneNumber = getSequenceNumber(1);
        for (List<Integer> integers : oneNumber) {
            SoltEntity one = soltEntityMap.get(integers.get(0));
            List<QAEntity> qaEntities = getQAEntityByKind(one, null, null, null, allSoltMap, "T001");
            allEntityList.addAll(qaEntities);
        }
        ExcelUtil.createExcel(allEntityList, OUT_PATH + catalogue + code + 5 + ".xls");
        allEntityList = new ArrayList<>();

        // 两种
        List<List<Integer>> twoNumber = getSequenceNumber(2);
        for (List<Integer> integers : twoNumber) {
            SoltEntity one = soltEntityMap.get(integers.get(0));
            SoltEntity two = soltEntityMap.get(integers.get(1));
            List<QAEntity> qaEntities = getQAEntityByKind(one, two, null, null, allSoltMap, "T002");
            allEntityList.addAll(qaEntities);
        }
        ExcelUtil.createExcel(allEntityList, OUT_PATH + catalogue + code + 6 + ".xls");
        allEntityList = new ArrayList<>();

        // 三种
        List<List<Integer>> threeNumber = getSequenceNumber(3);
        for (List<Integer> integers : threeNumber) {
            SoltEntity one = soltEntityMap.get(integers.get(0));
            SoltEntity two = soltEntityMap.get(integers.get(1));
            SoltEntity three = soltEntityMap.get(integers.get(2));
            List<QAEntity> qaEntities = getQAEntityByKind(one, two, three, null, allSoltMap, "T003");
            allEntityList.addAll(qaEntities);
        }
        ExcelUtil.createExcel(allEntityList, OUT_PATH + catalogue + code + 7 + ".xls");

    }

    /**
     * 当没有集合四时，按照三三组合，当没有集合二时，按照二二组合，一次类推
     *
     * @param one        集合一
     * @param two        集合二
     * @param three      集合三
     * @param four       集合四
     * @param allSoltMap Map<词槽名称，Map<词槽描述，词槽信息Entity>
     * @param fileName   文件名称
     * @return
     */
    private static List<QAEntity> getQAEntityByKind(SoltEntity one, SoltEntity two, SoltEntity three, SoltEntity four, Map<String, Map<String, TimeEntity>> allSoltMap, String fileName) {


        Map<String, TimeEntity> topicMap = allSoltMap.get("topic");
        Map<String, TimeEntity> personNumMap = allSoltMap.get("personNum");
        Map<String, TimeEntity> timeMap = allSoltMap.get("time");

        List<QAEntity> qaEntities = new ArrayList<>();
        int allCount = 1;

        if (ObjectUtil.isEmpty(two)) {
            List<String> oneSolts = one.getSolts();
            for (String oneSolt : oneSolts) {
                String template = "/answer";
                Random random = new Random();
                String punctuationOne = LIST_PUNCTUATION.get(random.nextInt(LIST_PUNCTUATION.size()));
                Map<String, Object> map = new HashMap<>();

                int count = 0;
                String topic = judegOther(Arrays.asList(topicMap.get(oneSolt)));
                if (!StringUtils.isEmpty(topic)) {
                    map.put("value" + count, topic);
                    map.put("key" + count, "topic");
                    count++;
                }
                String personNum = judegOther(Arrays.asList(personNumMap.get(oneSolt)));
                if (!StringUtils.isEmpty(personNum)) {
                    map.put("value" + count, personNum);
                    map.put("key" + count, "personNum");
                    count++;
                }
                TimeEntity timeEntity = judegTime(Arrays.asList(timeMap.get(oneSolt)));
                if (ObjectUtil.isNotEmpty(timeEntity)) {
                    String timeTemplate = timeEntity.getTimeTemplate();
                    map.put("value" + count, timeTemplate);
                    map.put("key" + count, "startTime");
                    count++;
                    String room = timeEntity.getRoomName();
                    map.put("value" + count, room);
                    map.put("key" + count, "room");
                    count++;
                    template = template + "One";
                }

                map.put("sentence", oneSolt + punctuationOne);
                String questionContent = FtlUtil.generateContent(map, FREEMARKER_BASE_PATH + fileName + "/question.ftl");
                String answerContent = FtlUtil.generateContent(map, FREEMARKER_BASE_PATH + fileName + template + ".ftl");
                qaEntities.add(new QAEntity("" + allCount, "", questionContent, answerContent));
                allCount++;
            }

        } else if (ObjectUtil.isEmpty(three)) {
            List<String> oneSolts = one.getSolts();
            List<String> twoSolts = two.getSolts();
            for (String oneSolt : oneSolts) {
                for (String twoSolt : twoSolts) {
                    String template = "/answer";
                    Random random = new Random();
                    String punctuationOne = LIST_PUNCTUATION.get(random.nextInt(LIST_PUNCTUATION.size()));
                    String punctuationTwo = LIST_PUNCTUATION.get(random.nextInt(LIST_PUNCTUATION.size()));
                    Map<String, Object> map = new HashMap<>();

                    int count = 0;

                    String topic = judegOther(Arrays.asList(topicMap.get(oneSolt), topicMap.get(twoSolt)));
                    if (!StringUtils.isEmpty(topic)) {
                        map.put("value" + count, topic);
                        map.put("key" + count, "topic");
                        count++;
                    }
                    String personNum = judegOther(Arrays.asList(personNumMap.get(oneSolt), personNumMap.get(twoSolt)));
                    if (!StringUtils.isEmpty(personNum)) {
                        map.put("value" + count, personNum);
                        map.put("key" + count, "personNum");
                        count++;
                    }
                    TimeEntity timeEntity = judegTime(Arrays.asList(timeMap.get(oneSolt), timeMap.get(twoSolt)));
                    if (ObjectUtil.isNotEmpty(timeEntity)) {
                        String timeTemplate = timeEntity.getTimeTemplate();
                        map.put("value" + count, timeTemplate);
                        map.put("key" + count, "startTime");
                        count++;
                        String room = timeEntity.getRoomName();
                        map.put("value" + count, room);
                        map.put("key" + count, "room");
                        count++;
                        template = template + "One";
                    }

                    if (allCount % 2 == 0) {
                        map.put("sentence", oneSolt + punctuationOne + twoSolt + punctuationTwo);
                    } else {
                        map.put("sentence", getHonorific() + oneSolt + punctuationOne + twoSolt + punctuationTwo);
                    }
                    map.put("sentence", oneSolt + punctuationOne + twoSolt + punctuationTwo);
                    String questionContent = FtlUtil.generateContent(map, FREEMARKER_BASE_PATH + fileName + "/question.ftl");
                    String answerContent = FtlUtil.generateContent(map, FREEMARKER_BASE_PATH + fileName + template + ".ftl");
                    qaEntities.add(new QAEntity("" + allCount, "", questionContent, answerContent));
                    allCount++;
                }
            }

        } else if (ObjectUtil.isEmpty(four)) {
            List<String> oneSolts = one.getSolts();
            List<String> twoSolts = two.getSolts();
            List<String> threeSolts = three.getSolts();
            for (String oneSolt : oneSolts) {
                for (String twoSolt : twoSolts) {
                    for (String threeSolt : threeSolts) {
                        String template = "/answer";
                        Random random = new Random();
                        String punctuationOne = LIST_PUNCTUATION.get(random.nextInt(LIST_PUNCTUATION.size()));
                        String punctuationTwo = LIST_PUNCTUATION.get(random.nextInt(LIST_PUNCTUATION.size()));
                        String punctuationThree = LIST_PUNCTUATION.get(random.nextInt(LIST_PUNCTUATION.size()));
                        Map<String, Object> map = new HashMap<>();

                        int count = 0;
                        String topic = judegOther(Arrays.asList(topicMap.get(oneSolt), topicMap.get(twoSolt), topicMap.get(threeSolt)));
                        if (!StringUtils.isEmpty(topic)) {
                            map.put("value" + count, topic);
                            map.put("key" + count, "topic");
                            count++;
                        }
                        String personNum = judegOther(Arrays.asList(personNumMap.get(oneSolt), personNumMap.get(twoSolt), personNumMap.get(threeSolt)));
                        if (!StringUtils.isEmpty(personNum)) {
                            map.put("value" + count, personNum);
                            map.put("key" + count, "personNum");
                            count++;
                        }
                        TimeEntity timeEntity = judegTime(Arrays.asList(timeMap.get(oneSolt), timeMap.get(twoSolt), timeMap.get(threeSolt)));
                        if (ObjectUtil.isNotEmpty(timeEntity)) {
                            String timeTemplate = timeEntity.getTimeTemplate();
                            map.put("value" + count, timeTemplate);
                            map.put("key" + count, "startTime");
                            count++;
                            String room = timeEntity.getRoomName();
                            map.put("value" + count, room);
                            map.put("key" + count, "room");
                            count++;
                            template = template + "One";
                        }
                        if (allCount % 2 == 0) {
                            map.put("sentence", oneSolt + punctuationOne + twoSolt + punctuationTwo + threeSolt + punctuationThree);
                        } else {
                            map.put("sentence", getHonorific() + oneSolt + punctuationOne + twoSolt + punctuationTwo + threeSolt + punctuationThree);
                        }
                        String questionContent = FtlUtil.generateContent(map, FREEMARKER_BASE_PATH + fileName + "/question.ftl");
                        String answerContent = FtlUtil.generateContent(map, FREEMARKER_BASE_PATH + fileName + template + ".ftl");
                        qaEntities.add(new QAEntity("" + allCount, "", questionContent, answerContent));
                        allCount++;
                    }
                }
            }
        }

        return random50List(qaEntities);
    }

    /**
     * 获取首段描述（如：尊称）
     *
     * @return
     */
    public static String getHonorific() {
        List<String> greetings = Arrays.asList(
                "尊敬的领导",
                "尊敬的先生",
                "尊敬的女士",
                "尊敬的同事",
                "敬爱的领导",
                "尊贵的长者",
                "尊重的上级",
                "敬请关照",
                "王五告诉我",
                "李四和我说"
        );

        return getRandomElementAndPunctuation(greetings);
    }

    /**
     * 随机取值 + 标点
     *
     * @param list 随机集合
     * @return
     */
    private static String getRandomElementAndPunctuation(List<String> list) {
        Random random = new Random();
        int randomIndex = random.nextInt(list.size());
        int punctuationRandomIndex = random.nextInt(LIST_PUNCTUATION.size());
        String punctuationOne = LIST_PUNCTUATION.get(punctuationRandomIndex);
        return list.get(randomIndex) + punctuationOne;
    }

    /**
     * 随机取值
     *
     * @param list 随机集合
     * @return
     */
    private static String getRandomElement(List<String> list) {
        Random random = new Random();
        int randomIndex = random.nextInt(list.size());
        return list.get(randomIndex);
    }

    /**
     * 校验其他元素
     *
     * @param timeEntitys
     * @return
     */
    private static String judegOther(List<TimeEntity> timeEntitys) {
        if (CollectionUtil.isEmpty(timeEntitys)) {
            return "";
        }
        for (TimeEntity timeEntity : timeEntitys) {
            if (ObjectUtil.isNotEmpty(timeEntity) && !StringUtils.isEmpty(timeEntity.getOther())) {
                return timeEntity.getOther();
            }
        }
        return "";
    }

    /**
     * 校验时间元素
     *
     * @param timeEntitys
     * @return
     */
    private static TimeEntity judegTime(List<TimeEntity> timeEntitys) {
        if (CollectionUtil.isEmpty(timeEntitys)) {
            return null;
        }
        for (TimeEntity timeEntity : timeEntitys) {
            if (ObjectUtil.isNotEmpty(timeEntity) && !StringUtils.isEmpty(timeEntity.getTimeTemplate())) {
                return timeEntity;
            }
        }
        return null;
    }

    /**
     * 随机在集合中抽取元素
     *
     * @param allList
     * @return
     */
    public static List<QAEntity> random50List(List<QAEntity> allList) {
        if (allList.size() > 200) {
            List<QAEntity> newList = new ArrayList<>();
            for (int i = 0; i < 200; i++) {
                newList.add(allList.get(RandomUtil.randomInt(0, allList.size())));
            }
            return newList;
        } else {
            return allList;
        }
    }

    /**
     * 随机在集合中抽取元素
     *
     * @param allList
     * @return
     */
    public static List<String> random200List(List<String> allList) {
        if (allList.size() > 20) {
            List<String> newList = new ArrayList<>();
            for (int i = 0; i < 20; i++) {
                newList.add(allList.get(RandomUtil.randomInt(0, allList.size())));
            }
            return newList;
        } else {
            return allList;
        }
    }

    /**
     * 获取随机排列组合
     *
     * @param size 排列组合元素个数
     * @return
     */
    public static List<List<Integer>> getSequenceNumber(Integer size) {
        List<Integer> numbers = Arrays.asList(0, 1, 2);
        List<List<Integer>> combinations = generateUnorderedDataUnorderedCombinations(numbers, size);
        combinations = combinations.stream().distinct().collect(Collectors.toList());

        List<List<Integer>> sortNumbers = new ArrayList<>();
        // 打印所有无序数据且无序组合
        for (List<Integer> combination : combinations) {
            Set<Integer> set = new HashSet<>(combination);
            if (set.size() == combination.size()) {
                sortNumbers.add(combination);
            }
        }
        return sortNumbers;
    }

    /**
     * 生成无序数据无序组合
     *
     * @param numbers
     * @param size
     * @return
     */
    public static List<List<Integer>> generateUnorderedDataUnorderedCombinations(List<Integer> numbers, int size) {
        List<List<Integer>> result = new ArrayList<>();
        generateUnorderedDataUnorderedCombinationsHelper(numbers, size, new ArrayList<>(), result);
        return result;
    }

    /**
     * 生成无序数据无序组合助手
     *
     * @param numbers
     * @param size
     * @param current
     * @param result
     */
    public static void generateUnorderedDataUnorderedCombinationsHelper(List<Integer> numbers, int size, List<Integer> current, List<List<Integer>> result) {
        if (size == 0) {
            // 在添加到结果前进行洗牌
            Collections.shuffle(current);
            result.add(new ArrayList<>(current));
            return;
        }

        for (int i = 0; i < numbers.size(); i++) {
            current.add(numbers.get(i));
            generateUnorderedDataUnorderedCombinationsHelper(numbers, size - 1, current, result);
            current.remove(current.size() - 1);
        }
    }


    /**
     * 会议主要词槽
     *
     * @return
     */
    private static List<String> getTopicWordSlot(Map<String, TimeEntity> topicWordMap) {
        List<String> topicWordList = Arrays.asList(
                "周例会",
                "月度总结会",
                "季度业务分析会",
                "年度工作总结会",
                "部门例会",
                "项目进度汇报会",
                "人事调整讨论会",
                "新员工培训交流会",
                "销售策略讨论会",
                "市场营销分析会",
                "员工生日会",
                "健康知识讲座",
                "公司年会",
                "公司团建活动",
                "部门团建活动",
                "产品推介会",
                "业务拓展交流会",
                "员工座谈会",
                "员工大会",
                "安全培训会议",
                "企业社会责任讨论会",
                "外部培训课程",
                "团队建设活动日",
                "部门年度计划会议",
                "月度业务汇报会议",
                "新项目启动会议",
                "公司发展战略规划会议",
                "技术研讨会",
                "行政事务协调会议"
        );
        List<String> names = new ArrayList<>();
        for (String topocWordSlotOne : LIST_TOPIC_WORD_SLOT_ONE) {
            String topocWord = getRandomElement(topicWordList);
            if (topocWordSlotOne == "") {
                for (String topocWordSlotThree : LIST_TOPIC_WORD_SLOT_THREE) {
                    String key = topocWordSlotThree + topocWord;
                    names.add(key);
                    topicWordMap.put(key, TimeEntity.builder().other(topocWord).build());
                }
            } else {
                for (String topocWordSlotTwo : LIST_TOPIC_WORD_SLOT_TWO) {
                    for (String topocWordSlotThree : LIST_TOPIC_WORD_SLOT_THREE) {
                        String key = topocWordSlotOne + topocWordSlotTwo + topocWordSlotThree + topocWord;
                        names.add(key);
                        topicWordMap.put(key, TimeEntity.builder().other(topocWord).build());
                    }
                }
            }
        }

        return names;
    }

    /**
     * 人数规格词槽
     *
     * @return
     */
    private static List<String> getPersonNumSlot(Map<String, TimeEntity> personNumSlotMap) {
        List<String> personNumSlotList = Arrays.asList(
                "4人",
                "5人",
                "6人",
                "7人",
                "8人",
                "9人",
                "10人",
                "11人",
                "12人",
                "13人",
                "14人",
                "15人",
                "16人",
                "三个人",
                "四个人",
                "五个人",
                "六个人",
                "七个人",
                "八个人",
                "九个人",
                "十个人",
                "三人",
                "四人",
                "五人",
                "六人",
                "七人",
                "八人",
                "九人",
                "十人"
        );

        Map<String, String> personNumSlotMapOther = new HashMap<>();
        personNumSlotMapOther.put("4人", "4");
        personNumSlotMapOther.put("5人", "5");
        personNumSlotMapOther.put("6人", "6");
        personNumSlotMapOther.put("7人", "7");
        personNumSlotMapOther.put("8人", "8");
        personNumSlotMapOther.put("9人", "9");
        personNumSlotMapOther.put("10人", "10");
        personNumSlotMapOther.put("11人", "11");
        personNumSlotMapOther.put("12人", "12");
        personNumSlotMapOther.put("13人", "13");
        personNumSlotMapOther.put("14人", "14");
        personNumSlotMapOther.put("15人", "15");
        personNumSlotMapOther.put("16人", "16");
        personNumSlotMapOther.put("三个人", "3");
        personNumSlotMapOther.put("四个人", "4");
        personNumSlotMapOther.put("五个人", "5");
        personNumSlotMapOther.put("六个人", "6");
        personNumSlotMapOther.put("七个人", "7");
        personNumSlotMapOther.put("八个人", "8");
        personNumSlotMapOther.put("九个人", "9");
        personNumSlotMapOther.put("十个人", "10");
        personNumSlotMapOther.put("三人", "3");
        personNumSlotMapOther.put("四人", "4");
        personNumSlotMapOther.put("五人", "5");
        personNumSlotMapOther.put("六人", "6");
        personNumSlotMapOther.put("七人", "7");
        personNumSlotMapOther.put("八人", "8");
        personNumSlotMapOther.put("九人", "9");
        personNumSlotMapOther.put("十人", "10");

        List<String> personNumSlots = new ArrayList<>();
        for (String identityCardStr : personNumSlotList) {
            String personNumSlotOne = getRandomElement(LIST_PERSON_NUM_SLOT_ONE);
            String key = personNumSlotOne  + identityCardStr;
            personNumSlots.add(key);
            personNumSlotMap.put(key, TimeEntity.builder().other(personNumSlotMapOther.get(identityCardStr)).build());
        }
        return personNumSlots;
    }

}
